package com.d5xx.hunters.API;

import com.d5xx.hunters.Variables;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.WorldCreator;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.io.File;

import static com.d5xx.hunters.Variables.*;

@SuppressWarnings("unused")
public class Hunter {
    private static final Map<Player, HunterPlayer> playerMap = new HashMap<>();
    private static final Map<String, YamlConfiguration> languageMap = new HashMap<>();
    private static final Map<World, HunterGame> gameMap = new HashMap<>();

    public static void addPlayer(Player player, HunterPlayer hunterPlayer) {
        playerMap.put(player, hunterPlayer);
    }

    public static void removePlayer(Player player) {
        playerMap.remove(player);
    }

    public static HunterPlayer getHunterPlayer(Player player) {
        return playerMap.get(player);
    }

    public static ArrayList<HunterPlayer> getAllHunterPlayers() {
        return new ArrayList<>(playerMap.values());
    }

    public static HunterGame getGame(World world) { return gameMap.get(world); }

    public static void addGame(List<World> worlds, HunterGame hunterGame) {
        for (World world : worlds) {
            gameMap.put(world, hunterGame);
        }
    }

    public static void loadAllLangs() {
        File[] files = Variables.langFolder.listFiles();
        if (files == null) return;
        for (File file : files) {
            if (!file.isFile()) {
                continue;
            }
            String fileName = file.getName();
            String[] splits = fileName.split("\\.");
            if (!splits[splits.length - 1].equalsIgnoreCase("yml")) {
                continue;
            }
            fileName = String.join("", Arrays.copyOfRange(splits, 0, splits.length - 1));
            if (languageMap.containsKey(fileName)) {
                languageMap.replace(fileName, YamlConfiguration.loadConfiguration(file));
            } else {
                languageMap.put(fileName, YamlConfiguration.loadConfiguration(file));
            }
        }
    }

    public static YamlConfiguration getLanguageCon(String fileName) {
        return languageMap.get(fileName);
    }

    public static ArrayList<HunterPlayer> getOnlinePlayer() {
        ArrayList<HunterPlayer> list = new ArrayList<>();
        for (Player player : Bukkit.getOnlinePlayers()) { //遍历所有在线玩家并踢出服务器
            HunterPlayer hunterPlayer = Hunter.getHunterPlayer(player);
            list.add(hunterPlayer);
        }
        return list;
    }
    public static ArrayList<HunterPlayer> getLobbyPlayer() {
        ArrayList<HunterPlayer> list = new ArrayList<>();
        for (Player player : Bukkit.getOnlinePlayers()) {
            HunterPlayer hunterPlayer = Hunter.getHunterPlayer(player);
            if (hunterPlayer.getType().equals("lobby") | hunterPlayer.getType().equals("waiting")) list.add(hunterPlayer);
        }
        return list;
    }

    public static ArrayList<HunterPlayer> getWaitingPlayer() {
        ArrayList<HunterPlayer> list = new ArrayList<>();
        for (Player player : Bukkit.getOnlinePlayers()) {
            HunterPlayer hunterPlayer = Hunter.getHunterPlayer(player);
            if (hunterPlayer.getType().equals("lobby-waiting")) list.add(hunterPlayer);
        }
        return list;
    }

    public static ArrayList<HunterPlayer> getGamingPlayer() {
        ArrayList<HunterPlayer> list = new ArrayList<>();
        for (Player player : Bukkit.getOnlinePlayers()) {
            HunterPlayer hunterPlayer = Hunter.getHunterPlayer(player);
            if (hunterPlayer.getType().equals("game") | hunterPlayer.getType().equals("game-fall")) list.add(hunterPlayer);
        }
        return list;
    }

    public static void saveAllPlayersSettings() {
        File storageFile = new File(dataFolder, "storage.yml");
        YamlConfiguration storage = YamlConfiguration.loadConfiguration(storageFile);
        List<HunterPlayer> hunterPlayerList = Hunter.getAllHunterPlayers();
        for (HunterPlayer hunterPlayer : hunterPlayerList) {
            storage.set("players." + hunterPlayer.getPlayerUUID().toString(), hunterPlayer.getSettingsMap());
        }
        try {
            storage.save(storageFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static Location getLobby() {
        YamlConfiguration storage = YamlConfiguration.loadConfiguration(new File(dataFolder, "storage.yml"));
        return new Location(
                Bukkit.getWorld(Objects.requireNonNull(storage.getString("lobby.world"))),
                Double.parseDouble(Objects.requireNonNull(storage.getString("lobby.x"))),
                Double.parseDouble(Objects.requireNonNull(storage.getString("lobby.y"))),
                Double.parseDouble(Objects.requireNonNull(storage.getString("lobby.z"))),
                Float.parseFloat(Objects.requireNonNull(storage.getString("lobby.yaw"))),
                Float.parseFloat(Objects.requireNonNull(storage.getString("lobby.pitch")))
        );
    }

    public static void initWorld(String text) {
        //卸载原本的下界与末地
        //Bukkit.unloadWorld(Objects.requireNonNull(Bukkit.getWorld("world_nether")), false);
        //Bukkit.unloadWorld(Objects.requireNonNull(Bukkit.getWorld("world_the_end")), false);

        for (int i = 0; i < config.getInt("settings.worldlist-size"); i++) {

            logger.info(ConsoleColor.yellow() + text + ConsoleColor.cyan() + (" gameMap_" + i) + "!" + ConsoleColor.reset());

            // 生成主世界
            World w = new WorldCreator("gameMap_" + i).createWorld();
            worldNameList.add("gameMap_" + i);
            worldList.add(w);
            //assert w != null;
            //Bukkit.unloadWorld(w, false);

            // 生成下界
            World w_n = new WorldCreator("gameMap_" + i + "_nether").environment(World.Environment.NETHER).createWorld();
            netherNameList.add("gameMap_" + i + "_nether");
            netherList.add(w_n);
            //assert w_n != null;
            //Bukkit.unloadWorld(w_n, false);

            // 生成末地
            World w_t_e = new WorldCreator("gameMap_" + i + "_the_end").environment(World.Environment.THE_END).createWorld();
            theEndNameList.add("gameMap_" + i + "_the_end");
            theEndList.add(w_t_e);
            //assert w_t_e != null;
            //Bukkit.unloadWorld(w_t_e, false);
        }
    }

    public static List<World> getRandomWorld() {
        World world = new WorldCreator(worldNameList.get(new Random().nextInt(worldNameList.size()))).createWorld();
        World world_nether = new WorldCreator(netherNameList.get(new Random().nextInt(netherNameList.size()))).createWorld();
        World world_the_end = new WorldCreator(theEndNameList.get(new Random().nextInt(theEndNameList.size()))).createWorld();
        worldList.remove(world);
        netherList.remove(world_nether);
        theEndList.remove(world_the_end);
        toDeleteWorldLsit.addAll(Arrays.asList(world, world_nether, world_the_end));
        return Arrays.asList(world, world_nether, world_the_end);
    }

    public static List<World> getWorld() {
        World world = Bukkit.getWorld(worldNameList.get(new Random().nextInt(worldNameList.size())));
        World world_nether = Bukkit.getWorld(netherNameList.get(new Random().nextInt(netherNameList.size())));
        World world_the_end = Bukkit.getWorld(theEndNameList.get(new Random().nextInt(theEndNameList.size())));
        worldList.remove(world);
        netherList.remove(world_nether);
        theEndList.remove(world_the_end);
        toDeleteWorldLsit.addAll(Arrays.asList(world, world_nether, world_the_end));
        return Arrays.asList(world, world_nether, world_the_end);
    }

    public static boolean deleteFolder(Path directoryPath) {
        // 指定要删除的目录路径
        try {
            // 使用Files.walkFileTree来递归访问给定的目录和子目录
            Files.walkFileTree(directoryPath, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    // 删除文件
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    // 目录中的所有文件都已访问完毕后，删除目录本身
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
            return true;
        } catch (IOException e) {
            return false;
        }
    }


    public static void deleteWorld() {
        for (World world : toDeleteWorldLsit) {
            String message;
            if (Bukkit.unloadWorld(world, true)) {
                logger.info( ConsoleColor.cyan() + "Unload world " + world.getName() + " successfully,"+ ConsoleColor.cyan() + " preparing delete it!" + ConsoleColor.reset());
                if (deleteFolder(Path.of(serverFolder + "\\" + world.getName()))) {
                    logger.info( ConsoleColor.cyan() + "Delete world " + world.getName() + " successfully!" + ConsoleColor.reset());
                }else {
                    logger.info( ConsoleColor.red() + "Failed to delete world " + ConsoleColor.cyan() + world.getName() + "!" + ConsoleColor.reset());
                }
            } else {
                logger.info( ConsoleColor.red() + "Failed to unload world " + world.getName() + "!" + ConsoleColor.reset());
            }
        }
    }

    public static void dropPlayerItems(Player player) {
        // 获取玩家背包中的物品
        ItemStack[] contents = player.getInventory().getContents();

        // 清空玩家背包
        player.getInventory().clear();

        // 将玩家背包中的物品掉落在当前位置
        for (ItemStack item : contents) {
            if (item != null) {
                player.getWorld().dropItemNaturally(player.getLocation(), item);
            }
        }
    }

    public static Map<String, Object> getPlayerSettings(UUID playerUUID) {
        ConfigurationSection defultSettings = config.getConfigurationSection("players.default-settings");
        YamlConfiguration storage = YamlConfiguration.loadConfiguration(new File(Variables.dataFolder, "storage.yml"));
        ConfigurationSection section = storage.getConfigurationSection("players." + playerUUID.toString());
        Map<String, Object> map = new HashMap<>();
        if (section != null) {
            for (String key : section.getKeys(false)) {
                if (section.isConfigurationSection(key)) {
                    continue;
                }
                map.put(key, section.get(key));
            }
        }
        if (defultSettings == null) {
            return map;
        }
        for (String key : defultSettings.getKeys(false)) {
            if (map.containsKey(key)) {
                continue;
            }
            if (defultSettings.isConfigurationSection(key)) {
                continue;
            }
            map.put(key, defultSettings.get(key));
        }
        return map;
    }
}
